(function( $, undefined ) {
		
    /*
	 * HoverDir object.
	 */
    $.HoverDir 				= function( options, element ) {
	
        this.$el	= $( element );
		
        this._init( options );
		
    };
	
    $.HoverDir.defaults 	= {
        hoverDelay	: 0,
        reverse		: false
    };
	
    $.HoverDir.prototype 	= {
        _init 				: function( options ) {
			
            this.options 		= $.extend( true, {}, $.HoverDir.defaults, options );
			
            // load the events
            this._loadEvents();
			
        },
        _loadEvents			: function() {
			
            var _self = this;
			
            this.$el.on( 'mouseenter.hoverdir, mouseleave.hoverdir', function( event ) {
				
                var $el			= $(this),
                evType		= event.type,
                $hoverElem	= $el.find( 'div' ),
                direction	= _self._getDir( $el, {
                    x : event.pageX, 
                    y : event.pageY
                } ),
                hoverClasses= _self._getClasses( direction );
				
                $hoverElem.removeClass();
				
                if( evType === 'mouseenter' ) {
					
                    $hoverElem.hide().addClass( hoverClasses.from );
					
                    clearTimeout( _self.tmhover );
					
                    _self.tmhover	= setTimeout( function() {
						
                        $hoverElem.show( 0, function() {
                            $(this).addClass( 'da-animate' ).addClass( hoverClasses.to );
                        } );
						
					
                    }, _self.options.hoverDelay );
					
                }
                else {
				
                    $hoverElem.addClass( 'da-animate' );
					
                    clearTimeout( _self.tmhover );
					
                    $hoverElem.addClass( hoverClasses.from );
					
                }
					
            } );
			
        },
        // credits : http://stackoverflow.com/a/3647634
        _getDir				: function( $el, coordinates ) {
			
            /** the width and height of the current div **/
            var w = $el.width(),
            h = $el.height(),

            /** calculate the x and y to get an angle to the center of the div from that x and y. **/
            /** gets the x value relative to the center of the DIV and "normalize" it **/
            x = ( coordinates.x - $el.offset().left - ( w/2 )) * ( w > h ? ( h/w ) : 1 ),
            y = ( coordinates.y - $el.offset().top  - ( h/2 )) * ( h > w ? ( w/h ) : 1 ),
			
            /** the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);**/
            /** first calculate the angle of the point, 
				add 180 deg to get rid of the negative values
				divide by 90 to get the quadrant
				add 3 and do a modulo by 4  to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/
            direction = Math.round( ( ( ( Math.atan2(y, x) * (180 / Math.PI) ) + 180 ) / 90 ) + 3 )  % 4;
			
            return direction;
			
        },
        _getClasses			: function( direction ) {
			
            var fromClass, toClass;
			
            switch( direction ) {
                case 0:
                    // from top
                    ( !this.options.reverse ) ? fromClass = 'da-slideFromTop' : fromClass = 'da-slideFromBottom';
                    toClass		= 'da-slideTop';
                    break;
                case 1:
                    // from right
                    ( !this.options.reverse ) ? fromClass = 'da-slideFromRight' : fromClass = 'da-slideFromLeft';
                    toClass		= 'da-slideLeft';
                    break;
                case 2:
                    // from bottom
                    ( !this.options.reverse ) ? fromClass = 'da-slideFromBottom' : fromClass = 'da-slideFromTop';
                    toClass		= 'da-slideTop';
                    break;
                case 3:
                    // from left
                    ( !this.options.reverse ) ? fromClass = 'da-slideFromLeft' : fromClass = 'da-slideFromRight';
                    toClass		= 'da-slideLeft';
                    break;
            };
			
            return {
                from : fromClass, 
                to: toClass
            };
					
        }
    };
	
    var logError 			= function( message ) {
        if ( this.console ) {
            console.error( message );
        }
    };
	
    $.fn.hoverdir			= function( options ) {
	
        if ( typeof options === 'string' ) {
			
            var args = Array.prototype.slice.call( arguments, 1 );
			
            this.each(function() {
			
                var instance = $.data( this, 'hoverdir' );
				
                if ( !instance ) {
                    logError( "cannot call methods on hoverdir prior to initialization; " +
                        "attempted to call method '" + options + "'" );
                    return;
                }
				
                if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
                    logError( "no such method '" + options + "' for hoverdir instance" );
                    return;
                }
				
                instance[ options ].apply( instance, args );
			
            });
		
        } 
        else {
		
            this.each(function() {
			
                var instance = $.data( this, 'hoverdir' );
                if ( !instance ) {
                    $.data( this, 'hoverdir', new $.HoverDir( options, this ) );
                }
            });
		
        }
		
        return this;
		
    };
	
})( jQuery );